#include <kern/mmu.h>
#include <kern/memlayout.h>
#include <kern/trap.h>
#include <kern/sched.h>
#include <kern/monitor.h>
#include <kern//debug.h>
#include <trap.h>
#include <types.h>
#include <x86.h>
#include <string.h>

typedef void (*trap_handler)(struct trapframe_t* tf);

/* global vars */
extern uintptr_t vectors[];  // in kern/vectors.S: array of 256 entry pointers
// Interrupt descriptor table (shared by all CPUs).
static struct gatedesc idt[256];
static trap_handler handlers[256];

void trap_init(void)
{
	int i;
	// setup all handlers to run in kernel mode and clear interrupt
	// upon invokation
	for(i = 0; i < 256; i++)
		SETGATE(idt[i], 0, SEG_KCODE << 3, vectors[i], DPL_KERN);

	// setup user interrupts
	SETGATE(idt[T_SYSCALL], 1, SEG_KCODE << 3, vectors[T_SYSCALL], DPL_USER);
	SETGATE(idt[T_BRKPT], 1, SEG_KCODE << 3, vectors[T_BRKPT], DPL_USER);

	memset(handlers, 0, sizeof handlers);
	// TODO: add trap handlers
}

void trap_init_idt(void)
{
	lidt(idt, sizeof idt);
}

// called from trapentry.S only
void trap(struct trapframe_t* tf)
{
	monitor_write("recved interrupt number ");
	monitor_write_dec(tf->trapno);
	monitor_write(" err: ");
	monitor_write_hex(tf->err);
	monitor_write("\n");

	//if (handlers[tf->trapno])
	//	handlers[tf->trapno](tf);

	panic("not implemented");
}


